www.gusucode.com > 支持向量机工具箱 - LIBSVM OSU_SVM LS_SVM源码程序 > 支持向量机工具箱 - LIBSVM OSU_SVM LS_SVM\stprtool\linear\finite\lindemo.m

    function result = lindemo(action,hfigure,varargin)
% LINDEMO demo on the linear learning algorithms.
%
% LINDEMO demonstrates use of the algorithms which find 
%  linear decision hyperplane between two (dichotomy)
%  point sets. Input data must be 2-dimensional and
%  can be interactively created by the user.
%
%  The program vizualizes found hyperplane in the current 
%  algorithm step. Badly clasiffied point, which will be used 
%  by the algorithm for updating of the solution, is also
%  vizualized. Text description of the state of the tested 
%  algorithm is printed in the comment window.
%
%  Following algorithms can be tested:
%
%  Perceptron  - Perceptron learning rule.
%  Kozinec     - Kozinec's algorithm.
%  e-Kozinec   - Modified Kozinec's algorithm finding e-optimal solution.
%  LinearSVM   - linear version of the Supprot Vector Machines.
%
% Control:
%  Algorithm  - select algorithm for testing.
%  Epsilon    - input parameter for the EKOZINEC algorithm 
%               (see help ekozinec).
%  Iterations - number of iterations in one step.
%  Animation  - enable/dissable animation.
%
%  FIG2EPS     - export screen to the PostScript file.
%  Load data   - load input point sets from file.
%  Create data - invoke program for creating point sets.
%  Reset       - set the tested algorithm to the initial state.
%  Play        - run the tested algorithm.
%  Stop        - stop the running algorithm.
%  Step        - perform only one step.
%  Info        - invoke the info box.
%  Close       - close the program.
%
%
% See also PERCEPTR, KOZINEC, EKOZINEC, LINSVM.
%

% Statistical Pattern Recognition Toolbox, Vojtech Franc, Vaclav Hlavac
% (c) Czech Technical University Prague, http://cmp.felk.cvut.cz
% Written Vojtech Franc (diploma thesis) 26.02.2000, 15.5.2000
% Modifications
% 24. 6.00 V. Hlavac, comments polished.
% 11-dec-2000 V. Franc, a little increasing of code readibility
% 15-dec-2000

LINE_WIDTH=1;        % width of separation line
ANIM_STEPS=10;       % number of steps during the line animation
BORDER=0.2;          % minimal space between axis and points
DATA_IDENT='Finite sets, Enumeration';  % file identifier
ALGOS=['Perceptron';'Kozinec   ';'e-Kozinec ';  'LinearSVM '];
%       ;'p-sum     ';'p-sumv    ';'Navara    ';'Nav-homog ';...
%       'linprog   ']; % list of algos

% if number of arguments is less then 1, that means first call of this
% function. Every other calls set up at least argument action
if nargin < 1,
   action = 'initialize';
end

% what action is required ?
switch lower(action)

case 'initialize'
   % == Initialize user interface control and figure =======

   % == Figure =============================================
   left=0.1;
   width=0.8;
   bottom=0.1;
   height=0.8;
   hfigure=figure('Name','Linear discriminant function', ...
      'Visible','off',...
    'NumberTitle','off', ...
      'Units','normalized', ...
      'Position',[left bottom width height],...
      'Units','normalized', ...
      'tag','Lindemo',...
      'RendererMode','manual');

   % == Axes =========================================
   left=0.1;
   width=0.65;
   bottom=0.35;
   height=0.60;
   haxes1=axes(...
       'Units','normalized', ...
      'Box','on', ...
      'DrawMode','fast',...
      'UserData',[],...
      'Position',[left bottom width height]);
   xlabel('feature x');
   ylabel('feature y');

   % == Comment window =================================
   % Comment Window frame
   bottom=0.05;
   height=0.2;
   uicontrol( ...
        'Style','frame', ...
        'Units','normalized', ...
        'Position',[left bottom width height], ...
        'BackgroundColor',[0.5 0.5 0.5]);

   % Text label
   uicontrol( ...
        'Style','text', ...
        'Units','normalized', ...
        'Position',[left height-0.01 width 0.05], ...
        'BackgroundColor',[0.5 0.5 0.5], ...
        'ForegroundColor',[1 1 1], ...
        'String','Comment Window');

   % Edit window
   border=0.01;
   hconsole=uicontrol( ...
        'Style','edit', ...
        'HorizontalAlignment','left', ...
        'Units','normalized', ...
        'Max',10, ...
        'BackgroundColor',[1 1 1], ...
        'Position',[left+border bottom width-2*border height-0.05], ...
        'Enable','inactive',...
        'String','');


    % == Buttons ===========================================
    % -- Export to EPS ---------
   width=0.1;
   left=0.75-width;
   bottom=0.95;
   height=0.04;
   hbtclose = uicontrol(...
    'Units','Normalized', ...
      'Callback','fig2eps(gcf)',...
        'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','FIG2EPS');
   %----------------------------------

   % Close button
   left=0.8;
   bottom=0.05;
   height=0.05;
   width=0.15;
   hbtclose = uicontrol(...
    'Units','Normalized', ...
      'Callback','close(gcf)',...
        'ListboxTop',0, ...
        'Position',[left bottom width height], ...
        'String','Close');

   % Info button: call stanard info box
   bottom=bottom+1.5*height;
   hbtinfo = uicontrol(...
    'Units','Normalized', ...
      'Callback','lindemo(''info'',gcf)',...
        'ListboxTop',0, ...
        'Position',[left bottom width height], ...
        'String','Info');

   % Step button: perform one adaptation step
   bottom=bottom+1.5*height;
    hbtstep = uicontrol(...
      'Units','Normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','Step', ...
      'Callback','lindemo(''step'',gcf)');

   % Stop button: stop process of adaptation
   bottom=bottom+height;
   hbtstop = uicontrol(...
    'Units','Normalized', ...
        'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','Stop', ...
      'Callback','set(gcbo,''UserData'',1)',...
      'Enable','off');

   % Play button: start up adaptation
   bottom=bottom+height;
   hbtplay = uicontrol(...
    'Units','Normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','Play', ...
      'Callback','lindemo(''play'',gcf)');

   % Reset button: set up t = 0
   bottom=bottom+height;
    hbtreset = uicontrol(...
      'Units','Normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','Reset', ...
      'Callback','lindemo(''reset'',gcf)');

   % Creat data
   bottom=bottom+1.5*height;
    hbtcreat = uicontrol(...
      'Units','Normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','Create data', ...
      'Callback','lindemo(''creatdata'',gcf)');

   % Load data
   bottom=bottom+1*height;
    hbtload = uicontrol(...
      'Units','Normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'String','Load data', ...
      'Callback','lindemo(''getfile'',gcf)');

   % == Popup menus ======================================
   % Pop up menu for the selection between algorithms
    % title
   bottom=0.95-height;
   htxalgo=uicontrol( ...
      'Style','text', ...
      'Units','normalized', ...
      'Position',[left bottom width height], ...
      'String','Algorithm');
   % popup menu
   bottom=bottom-height;
   hpualgo=uicontrol( ...
      'Style','popup', ...
      'Units','normalized', ...
      'CallBack','lindemo(''epshandler'',gcf)',...
      'Position',[left bottom width height], ...
      'String',ALGOS);


   % == Edit line ========================================
   % epsilon
   bottom=bottom-1.2*height;
   htxeps=uicontrol( ...
      'Style','text', ...
      'Units','normalized', ...
      'Position',[left bottom width 0.9*height], ...
      'Enable','off',...
      'String','epsilon');
   bottom=bottom-height;
   hedeps = uicontrol(...
    'Units','normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'Style','edit',...
      'Enable','off',...
      'CallBack','lindemo(''epshandler'',gcf)',...
      'String','1e-3');

   % # of iterations
   bottom=bottom-1.1*height;
   htxiter=uicontrol( ...
      'Style','text', ...
      'Units','normalized', ...
      'Position',[left bottom width 0.9*height], ...
      'String','Iterations');

   bottom=bottom-0.9*height;
   hediter = uicontrol(...
    'Units','normalized', ...
      'ListboxTop',0, ...
        'Position',[left bottom width height], ...
      'Style','edit',...
      'CallBack','lindemo(''iterhandler'',gcf)',...
      'String','1');

   % == Check boxes ==============================================
   % Make check box to determine if a line will be drawn in one 
   % step or smooth plot.
   bottom=bottom-height*1.2;
    hxbanim = uicontrol(...
    'Style','checkbox', ...
    'Units','normalized', ...
    'ListboxTop',0, ...
    'Position',[left bottom width height], ...
    'String','Animation');

    % ============================================================
   % Store handlers
   handlers=struct(...
      'line',struct('handler',-1,'alpha',0,'theta',0,'t',0),...
      'btstep',hbtstep,...
      'btstop',hbtstop,...
      'btclose',hbtclose,...
      'btplay',hbtplay,...
      'btreset',hbtreset,...
      'btinfo',hbtinfo,...
      'btload',hbtload,...
      'btcreat',hbtcreat,...
      'pualgo',hpualgo,...
      'console',hconsole,...
      'editer',hediter,...
      'edeps',hedeps,...
      'txeps',htxeps,...
      'axes1',haxes1,...
      'xbanim',hxbanim);
   set(hfigure,'UserData',handlers)

   % Reset
   lindemo('reset',hfigure);

   % Put figure on desktop
   set(hfigure,'Visible','on');
   drawnow;

case 'iterhandler'
   % == Handler for edit line Iterations ===============
   h=get(hfigure,'UserData');

   iter=round(str2num(get(h.editer,'String')));
   if isempty(iter) | iter < 1, iter=1; end
   set(h.editer,'String',num2str(iter));


case 'epshandler'
   % == Handler for edit line Epsilon =======================
   h=get(hfigure,'UserData');

   % if algorithm e-Kozinec is selected then ...
   if get(h.pualgo,'Value')==3,
      set(h.edeps,'Enable','on');
      set(h.txeps,'Enable','on');

      epsil=str2num(get(h.edeps,'String'));
      if epsil < 0,
         epsil=1;
         set(h.edeps,'String',num2str(epsil));
      end
   else
      set(h.edeps,'Enable','off');
      set(h.txeps,'Enable','off');
   end


case 'creatdata'
   % == Invoke data set creator ================================
   creatset('finite',2,'lindemo','created',hfigure);


case 'created'
   % == Load new created data set =============================

   % get handler and make this figure active
   figure(hfigure);
   h=get(hfigure,'UserData');

   % get file name
   path=varargin{1};
   name=varargin{2};
   pathname=strcat(path,name);

   if checkdat(pathname,DATA_IDENT,2,[0 0])==1,
      file.pathname=pathname;
      file.path=path;
      file.name=name;
      set(h.btload,'UserData',file);
      lindemo('loadsets',hfigure);
      lindemo('reset',hfigure);
   else
      errordlg('This file does not contain required data.','Bad file','modal');
   end


case 'getfile'
   % == Invoke standard open file dialog ===================
   % Opens file and checks if contains appropriate data, 
   % if yes loads data.

   h=get(hfigure,'UserData');

   [name,path]=uigetfile('*.mat','Open file');
   if name~=0,
      file.pathname=strcat(path,name);
      file.path=path;
      file.name=name;
      if checkdat(file.pathname,DATA_IDENT,2,[0 0])==1,
         set(h.btload,'UserData',file);
         lindemo('loadsets',hfigure);
         lindemo('reset',hfigure);
      else
         errordlg('This file does not contain required data.','Bad file','modal');
      end
   end


case 'redraw'
   % == Redraw points in axes ==================================
   h=get(hfigure,'UserData');           % uicontrol handlers

   % get point sets
   sets=get(h.axes1,'UserData');
   if isempty(sets)==1,
      return;
   end

   % clears axes
   set(get(h.axes1,'Children'),'EraseMode','normal');
   clrchild(h.axes1);

   h.line.handler=line('EraseMode','xor','Color','k','Visible','off','Parent',h.axes1);
   set(hfigure,'UserData',h);                   % uicontrol handlers

%%%   pplot(sets.X,sets.I);
   ppoints(sets.X,sets.I);
   lindemo('drawline',hfigure,h.line.theta,h.line.alpha);

   drawnow;


case 'loadsets'
   % == Load data sets ========================================
   % Get file name from the pop up menu according to menu pointer. 
   % Than clear axes,load new file and appear the points from the file.

   h=get(hfigure,'UserData');

   % Clear axes
   clrchild(h.axes1);

   set(h.axes1, ...
      'Box','on', ...
      'DrawMode','fast' );
   xlabel('feature x');
   ylabel('feature y');

   % No line
   h.line.handler=-1;
   set(hfigure,'UserData',h);

   % Get file name with sets
   file=get(h.btload,'UserData');

   % Load sets
   sets=load(file.pathname);

   % store loaded sets
   set(h.axes1,'UserData',sets);

   % set axes according to current point set
   win=cmpwin(min(sets.X'),max(sets.X'),BORDER,BORDER);
   setaxis(h.axes1,win);

   axes(h.axes1);

   % plots points
   ppoints(sets.X,sets.I);

   drawnow;
   
   
case 'play'
   % == Start up the adaptation process ============================

   % Get handle to data.
   h=get(hfigure,'UserData');               

   if h.line.handler==-1,
      return;
   end

   % Check if data are loaded.
   sets=get(h.axes1,'UserData');
   if isempty(sets)==1,
      return;
   end

   % Disable and enable buttons.
   set([h.btinfo h.btstep h.btclose h.btplay h.btreset h.btload h.btcreat ...
       h.pualgo h.editer],'Enable','off');
   set(h.btstop,'Enable','on');

   set(h.btstop,'UserData',0);

   h.stop = 0;
   set(hfigure,'UserData',h);
   
   % Play - adaptation process
   while h.stop==0 & get(h.btstop,'UserData')==0,
      lindemo('step',hfigure);
      h=get(hfigure,'UserData');                  
   end

   % Enable and dissable buttons.
   set([h.btinfo h.btstep h.btclose h.btplay h.btreset h.pualgo ...
      h.editer h.btload h.btcreat],'Enable','on');
   set(h.btstop,'Enable','off');


case 'step'
   % == Perform one adaptation step ======================================
   h=get(hfigure,'UserData');        % get handlers we will need...

   if h.line.handler==-1,
      return;
   end

   % get sets
   sets=get(h.axes1,'UserData');

   % no data set loaded
   if isempty(sets)==1,
      return;
   end

   [alpha,theta,solution,t]=exec(hfigure);

   if mod(h.stepcnt,2)==1 & h.line.t >0, 
     if solution ~= 1,
        lindemo('drawline',hfigure,theta,alpha);
     else
        text=makeinfo(t,alpha,theta,solution);
        set(h.console,'String',text );
     end 
   else
      if get(h.xbanim,'Value')==0,
        lindemo('drawline',hfigure,theta,alpha);
      else
        lindemo('animline',hfigure,theta,alpha);
      end
   
      if solution==1 | solution==-1,
        h.stop=1;
      end
      h.line.alpha = alpha;
      h.line.theta = theta;
      h.line.t = t;
   
      if solution==0 | solution ==1,
         % appear time and line parameters
         text=makeinfo(t,alpha,theta,solution);
      elseif solution==-1,
        text=sprintf('Solution does not exist.\n');
      end 
      set(h.console,'String',text );
   end


   %  store new solution
   h.stepcnt=h.stepcnt+1;
   set(hfigure,'UserData',h);


case 'animline'
   % == Smooth transition of line from old to new position ===============

   h=get(hfigure,'UserData');                     % get handlers

   % old position of line is...
   alpha2=h.line.alpha;
   theta2=h.line.theta;
   t2=h.line.t;

   % New position get from input arguments
   theta1=varargin{1};
   alpha1=varargin{2};

   if t2~=0,
      % move line
    step=1/ANIM_STEPS;
       for k=0:step:1,
       alpha=(1-k)*alpha2+k*alpha1;      % smooth transition of alpha
        theta=(1-k)*theta2+k*theta1;      % --//--                      theta

          lindemo('drawline',hfigure,theta,alpha);
      end
   else
      % it is first step
      lindemo('drawline',hfigure,theta1,alpha1); % first step
   end % if t2~=0


case 'reset'
   % == Reset adaptation process, set up zero step ================

   h=get(hfigure,'UserData');                     % get handlers

   % get data set
   sets=get(h.axes1,'UserData');

   % get file
   file=get(h.btload,'UserData');

   % zeroize parameters of the separation line
   h.line.t=0;
   h.line.theta=0;
   h.line.alpha=[0;0];
   
   h.stepcnt=0;

   if h.line.handler==-1,
      % create line
      axes(h.axes1);
      
      h.line.handler=...
        line('EraseMode','xor','Color','k','Visible','off','Parent',h.axes1);

      h.badpoint.handler=line('EraseMode','xor','Color','k','Visible','off',...
       'Parent',h.axes1,...
       'Marker','o',...
       'MarkerSize',10);
      
      
      drawnow;
   else
      % change parameters of line
      set(h.line.handler,'Visible','off');
      set(h.badpoint.handler,'Visible','off');
   end % if hline==-1

   % set up handlers and flush queue with graph. objects
   set(hfigure,'UserData',h);

   % create comment
   if isempty(sets)==0,
      consoletext=sprintf('Step t=0\nNo separation line');
      titletext=sprintf('File: %s, # of points K = %d',file.name,sum(sets.K));
   else
      consoletext=sprintf('No data loaded.\nPress Load data button.\n');
      titletext='';

      pos=get(h.axes1,'Position');
      fsize=min(pos(3),pos(4))/10;
      setaxis(h.axes1,[-1 1 -1 1]);
      axis([-1 1 -1 1]);
      
      builtin('text',0,0,'Press ''Load data'' button.',...
         'HorizontalAlignment','center',...
         'FontUnits','normalized',...
         'Clipping','on',...
         'FontSize',fsize);
   end

   % show comment
   set(h.console,'String',consoletext );

   % print title
   pos=get(h.axes1,'Position');
   fsize=(1-pos(2)-pos(4))*1;
   title(titletext,...
      'Parent',h.axes1,...
      'VerticalAlignment','bottom',...
      'HorizontalAlignment','left',...
      'FontUnits','normalized',...
      'Units','normalized',...
      'Position',[0 1 0],...
      'FontSize',fsize);


case 'drawline'
   % == Draw separation line ============================

   h=get(hfigure,'UserData');              % get handlers

   % get new line position from input arguments
   theta=varargin{1};
   alpha=varargin{2};

   if mod(h.stepcnt,2)==1 & h.line.t >0, 
     set(h.badpoint.handler,'Visible','on',...
         'XData',alpha(1),'YData',alpha(2));
   else
     set(h.badpoint.handler,'Visible','off');
 
     % Cut off line along axes
     [x1,y1,x2,y2,in]=cliplin1(alpha,theta,getaxis(h.axes1));

     % erase old line
     set(h.line.handler,'Visible','off');

      % draw new line if is in the axes
      if in==1,
         set(h.line.handler,...
           'XData',[x1 x2],...
           'YData',[y1 y2],...
           'LineWidth',LINE_WIDTH,...
           'Visible','on');
      end
   end

    % flush draw queue
   drawnow;
 

case 'info'
   % == Invokes standard Matlab`s info box ==========================
   helpwin(mfilename);
end



%========================================
function [text]=makeinfo(t,alpha,theta,solution)
% assembles text description about current solution state

if solution==1,
   txline{1}=sprintf('Solution is found after t=%d step(s).',t);
else
   txline{1}=sprintf('Step t=%d',t);
end
txline{2}=sprintf('Linear function:');
txline{3}=sprintf('%f x + %f y = %f',alpha(1),alpha(2),theta);

text='';
for i=1:3,
   text=strvcat(text,txline{i});
end

return;


%===========================================
function [alpha,theta,solution,tplus1]=exec(hfigure);

h=get(hfigure,'UserData');                           

if h.line.handler==-1,
   return;
end

% get sets
sets=get(h.axes1,'UserData');

% no data set loaded
if isempty(sets)==1,
   return;
end

% get parameters
t=h.line.t;
alpha=h.line.alpha;
theta=h.line.theta;

iter=max(1,round(str2num(get(h.editer,'String'))));
epsil=str2num(get(h.edeps,'String'));

if mod(h.stepcnt,2) ~= 0 & t > 0,
  iter = -1;
end

% perform one adaptation step
switch get(h.pualgo,'Value')
 case 1
    [alpha,theta,solution,tplus1]=perceptr(sets.X,sets.I,iter,t,alpha,theta);
 case 2
    [alpha,theta,solution,tplus1]=kozinec(sets.X,sets.I,iter,t,alpha,theta);
 case 3
    [alpha,theta,solution,tplus1]=ekozinec(sets.X,sets.I,epsil,iter,t,...
                                           alpha,theta);      
 case 4
    [alpha,theta,solution]=linsvm(sets.X,sets.I);
    if solution==0, solution=-1; end
    tplus1=1;
 case 5
%    [alpha,theta,solution,tplus1]=psum(sets.X,sets.I,10,iter,t,alpha,theta);
% case 6
%    [alpha,theta,solution,tplus1]=psumv(sets.X,sets.I,iter,t,alpha,theta);
% case 7
%    [alpha,theta,solution,tplus1]=navara1(sets.X,sets.I,iter,t,alpha,theta);
% case 8
%    [alpha,theta,solution,tplus1]=navarah1(sets.X,sets.I,iter,t,alpha,theta);
% case 9
%    [alpha,theta,solution]=simplex(sets.X,sets.I);
%    if solution==0, solution=-1; end
%    tplus1=1;

end

return